1. /* sdfdreci.cpp by K.Tsuru */
  2. // function ID = 327 DRADIX
  3. /******************************************************
  4. SDouble class 1/a
  5. Provides a reciprocal of a.
  6. [Algorithm]
  7. Get a solusion of an equation a - 1/x = 0 by the
  8. Newton's method with "doubling effective figures"(DEF).
  9. It yileds a recurrence formula
  10. d=1-a*x(n)
  11. x(n+1)=x(n)+x(n)*d 2nd
  12. x(n+1)=x(n)(1+d+d*d) 3rd
  13. x(n+1)=x(n)(1+d)*(1+d*d) 4th
  14. ********************************************************/
  15. #ifndef SN_H
  16. #include "sn.h"
  17. #endif
  18. static const char* const func = "DReciprocal";
  19. #define USE_4TH_CONV_DRec 1
  20. SDouble DReciprocal(const SDouble& x){
  21. //Does not accept BRADIX.
  22. if( x.Type() != x.REAL ) x.SetError(x.RADIX_ERR, func, 327);
  23. if( x.Sign(327) == 0 ) x.SetError(x.DIVIDED_BY_ZERO, func, 327);
  24. //Check it can be expressed by a reciprocal of a short number including |x|==1.
  25. long L, dec_e;
  26. uint xf = x.Last() - x.First(); // 0.0001 2345 6000(xf = 2)=123456*10^(-9) Ok
  27. if( (xf <= 2u) && x.ConvTolongExp(&L, &dec_e) ){
  28. SDouble Ds;
  29. int v = x.Sign(327) > 0 ? 1 : -1;
  30. Ds = v;
  31. if( labs(L) != 1 ) Ds = DsDiv(Ds, (ulong)labs(L)); // 1/L, |L| <= SlOpMaxValue()
  32. if(dec_e) Ds.MultPow10(-dec_e);
  33. Ds.iterationCount = 0;
  34. return Ds;
  35. }
  36. //|x| != 1 in below.
  37. RealSize C;
  38. uint max_sz = x.MaxSize(); //not "CurrentMaxSize()"
  39. //delta is an additional value and vx = |x|.
  40. //It takes into irreducible maximum size mode.
  41. SDouble y(x.Type(), max_sz), delta(x.Type(), max_sz), vx(Dabs(x));
  42. int e = vx.NetRdxExp();
  43. //c:counter of iteration, itrmax:its maximum value
  44. uint c = 0, itrmax = howpow2( (DFIGURES*max_sz)/DOUBLE_FIG+1 ) + 7;
  45. uint ef = (DOUBLE_FIG*2u)/DFIGURES, fig = C.EffFigures();
  46. //cout << "fig = " << fig << endl;
  47. //Get an approximated value for 1/x.
  48. vx.MultPowRdx(1-e); //Set exponent at one. 1.0 < vx <= DRADIX
  49. double dblX = doubleD(vx);
  50. delta = dblX - vx;
  51. if( delta.Sign(327) ){
  52. //If dblX is very close to double value, high precision is necessary.
  53. ef = max( ef, 2u*(uint)abs(delta.NetRdxExp()) );
  54. }
  55. bool fullPrec = false; //It has evaluated in full perecision or not.
  56. y = 1.0/dblX;
  57. y.FixedPoint(y.RdxExp());
  58. if(ef > fig) ef = fig;
  59. #if USE_4TH_CONV_DRec //==============================
  60. int pre_exD = 0, now_exD = 0;
  61. //enter into fixed point mode
  62. do {
  63. if( (ef = C.SetEffFig(ef)) >= fig) fullPrec = true;
  64. delta = ONE - vx*y; //evaluate refering CurrentMaxSize()
  65. now_exD = delta.NetRdxExp();
  66. // In the good converge process, it satisfies now_exD < pre_exD < 0
  67. if(now_exD < pre_exD) pre_exD = now_exD;
  68. else break; // perhaps comverge
  69. if(fullPrec && delta.IsMLT(ONE)) {
  70. C.SetEffFig(0); break;
  71. }
  72. y = y*(ONE + delta)*(ONE + delta*delta) ;
  73. c++;
  74. ef *= 4u;
  75. if(ef > fig) ef = fig;
  76. C.SetEffFig(0);
  77. } while( (c < itrmax) || !fullPrec );
  78. //The condition "!delta.isHidden()" corresponds to refering relative error.
  79. //The condition "c < itrmax" is not necessary but to avoid endless running.
  80. #else // end of USE_4TH_CONV==============================
  81. // below 2nd convergence
  82. do {
  83. if( (ef = C.SetEffFig(ef)) >= fig) fullPrec = true;
  84. delta = ONE - vx*y; //evaluate refering CurrentMaxSize()
  85. delta = delta*y;
  86. y += delta;
  87. c++;
  88. ef *= 2u;
  89. if(ef > fig) ef = fig;
  90. C.SetEffFig(0);
  91. } while( ( !delta.IsHidden() && (c < itrmax) ) || !fullPrec );
  92. //The condition "!delta.isHidden()" corresponds to refering ralative error.
  93. //The condition "c < itrmax" is not necessary but to avoid endless running.
  94. #endif
  95. y.PointFree();
  96. if(c == itrmax) y.SetError(y.FATAL, func, 327);
  97. /*************************************************************
  98. Add a correction.
  99. Let d = 1-x*y'
  100. If d != 0
  101. y' = (1-d)/x = y*(1-d) ( y = 1/x )
  102. y = y'/(1-d) ~= y'*(1+d).
  103. Correction is y'*d
  104. It might not need.
  105. ***************************************************************/
  106. #if 1 // Changed from 1 to 0 on Jan 29, 2001.
  107. delta = ONE - vx*y;
  108. if(delta.Sign()){ //delta == 0 in almost case.
  109. ef = delta.Last()-delta.First() +delta.Hidden();
  110. SDouble ys = y.TakeOutFigures(ef);
  111. y = y + ys*delta;
  112. }
  113. #endif
  114. if(y.Verify()){ // y ~= 1.0
  115. delta = ONE - y*vx;
  116. if(!delta.IsMLT(ONE)){
  117. vx.SetError(vx.VERIFY, func, 327);
  118. }
  119. // for debug
  120. // cout << "in Verify() delta= " << delta << endl; Wait();
  121. }
  122. /******************************************************************************
  123. It rounds off if possible.
  124. If this procedure does not exist,a value such as 1/(BRDDIX^2) has an inaccuracy
  125. in the last few figures, though it is a finite decimal. Above correction
  126. cannot remove this inaccuracy.
  127. ********************************************************************************/
  128. if(y.IsPossibleToRound(3)) y.Round(0);
  129. y.iterationCount = c;
  130. if(x.Sign() < 0) y.ChangeSign();
  131. y.MultPowRdx(1-e); // includes Reform() function.
  132. return y;
  133. }

sdfdreci.cpp : last modifiled at 2017/08/07 15:49:23(4,892 bytes)
created at 2017/10/07 10:22:50
The creation time of this html file is 2017/10/07 11:29:39 (Sat Oct 07 11:29:39 2017).